<?php

namespace App\Http\Controllers\API\common;
use DB;
use Session;
use Cache;
use Storage;
class NBIotController
{
    protected $appId;
    protected $secret;
    protected $server = 'https://180.101.147.89:8743';
    protected $client = 'D:/wwwroot/CERT/client.crt';
    protected $key = 'D:/wwwroot/CERT/client.key';
    protected $Auth_path = '/iocm/app/sec/v1.1.0/login';
    protected $RToken_path = '/iocm/app/sec/v1.1.0/refreshToken';
    protected $add_devices_path = '/iocm/app/reg/v1.2.0/devices?appId=';
    protected $delete_devices_path = '/iocm/app/dm/v1.1.0/devices/';
    protected $update_devices_path = '/iocm/app/dm/v1.2.0/devices/';
    protected $create_command_path = '/iocm/app/cmd/v1.4.0/deviceCommands?appId=';

    public function __construct($appId ='', $secret = '')
    {
        if (empty($appId)) {
            $this->appId = 'kE05CD1VKn8e0n8lpQimiOYcjvIa';
        } else {
            $this->appId = $appId;
        }
        if (empty($secret)) {
            $this->secret = 'CDUnH88JkZYxxQ92SZ6tyorIl9ga';
        } else {
            $this->secret = $secret;
        }
    }

    protected function Auth ()
    {
        $app = Array
        (
            'appId' => $this->appId,
            'secret' => $this->secret
        );
        $auth = $this->server.$this->Auth_path; 
        $output = $this->post_url($auth, http_build_query($app), 'post');
        $code = json_decode($output,true);
        if (array_key_exists('accessToken',$code)) {
            //将access_token和refresh_token存入nb_token表
            DB::table('nb_abutment') -> where(['appId'=>$this->appId,'secret'=>$this->secret]) -> update(['accessToken'=>$code['accessToken'],'atExpiresIn'=>time()+$code['expiresIn']/2,'refreshToken'=>$code['refreshToken'],'rtExpiresIn'=>time()+3600*24*29]);
            $code['error_code'] = '0';
        }
        return $code;
    }

    protected function Refresh_Token ()
    {
        //判断refreshToken是否存在
        $res = DB::table('nb_abutment') -> where(['appId'=>$this->appId,'secret'=>$this->secret]) -> select('refreshToken','rtExpiresIn') -> first();
        //$bool = Storage::disk('local')->has('Refresh/one.txt');
        if ($res['refreshToken']) {
                if (time()<=$res['rtExpiresIn']) {
                    $app = Array
                    (
                        'appId' => $this->appId,
                        'secret' => $this->secret,
                        'refreshToken' => $res['refreshToken']
                    );
                    $Token_path =$this->server.$this->RToken_path;
                    $headers = Array
                        (
                            'Content-Type:application/json' 
                        );
                    $output = $this->post_url($Token_path, json_encode($app), 'post', $headers);
                    $code = json_decode($output,true);
                    if (array_key_exists('accessToken',$code)) {
                        //将access_token和refresh_token存入nb_token表
                        DB::table('nb_abutment') -> where(['appId'=>$this->appId,'secret'=>$this->secret]) -> update(['accessToken'=>$code['accessToken'],'atExpiresIn'=>time()+$code['expiresIn']/2,'refreshToken'=>$code['refreshToken'],'rtExpiresIn'=>time()+3600*24*29]);
                        $code['error_code'] = '0';
                        return $code;
                    }
                }
        }
        return $this->Auth();
    }

    protected function Token ()
    {
        $token = Array();
        //判断accessToken是否已失效
        $res = DB::table('nb_abutment') -> where(['appId'=>$this->appId,'secret'=>$this->secret]) -> select('accessToken','atExpiresIn') -> first();
        if (time()<$res['atExpiresIn']) {
            $token['accessToken'] = $res['accessToken'];
            $token['error_code'] = 0;
        } else {
            $token = $this->Refresh_Token();
        }
        return $token;
    }

    public function add_devices ($nodeId, $endUserId = '', $psk = '' ,$timeout = 0)
    {
        $token = $this->Token();
        if ($token['error_code'] == 0) {
            $add_devices_path =$this->server.$this->add_devices_path.$this->appId;
            $headers = Array
                (
                    'app_key:'.$this->appId,
                    'Authorization:Bearer '.$token['accessToken'],
                    'Content-Type:application/json'  
                );
            $app = Array
                (
                    'appId' => $this->appId,
                    'verifyCode' => $nodeId,
                    'nodeId' => $nodeId
                );
            if (!empty($endUserId)) {
                $app['endUserId'] = $endUserId;
            }
            if (!empty($psk)) {
                $app['psk'] = $psk;
            }
            if ($timeout == 0) {
                $app['timeout'] = $timeout;
            }
            $output = $this->post_url($add_devices_path, json_encode($app), 'post', $headers);
            $code = json_decode($output,true);
            return $code;
        } else {
            return $token;
        }
    }


    public function delete_devices ($devices)
    {
        $token = $this->Token();
        if ($token['error_code'] == 0 ) {
            $delete_devices_path =$this->server.$this->delete_devices_path.$devices.'?appId='.$this->appId;
            // return $delete_devices_path;
            $headers = Array
                (
                    'app_key:'.$this->appId,
                    'Authorization:Bearer '.$token['accessToken'],
                    'Content-Type:application/json'  
                );
                $output = $this->post_url($delete_devices_path, '', 'delete', $headers);
                return $output;
        } else {
            return $token;
        }
    }

    public function update_devices ($devices, $name = '', $manufacturerId = '0029', $manufacturerName = 'Sanqiwulian', $deviceType = 'Smoke', $protocolType = 'CoAP', $model = 'sqVH75', $location = 'Shenzhen', $mute ='')
    {
        $token = $this->Token();
        if($token['error_code'] == 0){
            $update_devices_path =$this->server.$this->update_devices_path.$devices.'?appId='.$this->appId;
            $headers = Array
                (
                    'app_key:'.$this->appId,
                    'Authorization:Bearer '.$token['accessToken'],
                    'Content-Type:application/json'  
                );
            $app = Array
                (
                    'name' => $name,
                    'manufacturerId' => $manufacturerId,
                    'manufacturerName' => $manufacturerName,
                    'location' => $location,
                    'deviceType' => $deviceType,
                    'protocolType' => $protocolType,
                    'model' => $model
                );
            $output = $this -> post_url($update_devices_path, json_encode($app) , 'put', $headers);
            return $output;
        }
        return $token;
    }

    //下发命令
    public function create_command($deviceId,$serviceId='Infrared',$state=1){
        $token = $this->Token();
        if($token['error_code'] == 0){
            $create_command_path = $this->server.$this->create_command_path.$this->appId;
            $headers = Array
            (
                'app_key:'.$this->appId,
                'Authorization:Bearer '.$token['accessToken'],
                'Content-Type:application/json'
            );
            $body = Array
            (
                "deviceId"=>$deviceId,
                'command'=>array(
                    'serviceId'=>$serviceId,
                    'method'=>'command',
                    'paras'=>array(
                        'State'=>$state
                    )
                ),
                "expireTime" => 0
            );
            $output = $this -> post_url($create_command_path, json_encode($body) , 'post', $headers);
            return $output;
        }

    }

    protected function post_url ($url, $data, $method = 'post', $headers='', $client ='', $key = '')
    {
        if (empty($client)) {
            $client = $this->client;
        }
        if (empty($key)) {
            $key = $this->key;
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        if (!empty($headers)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_SSLCERT, $client);
        curl_setopt($ch, CURLOPT_SSLKEY, $key);
        switch ($method) {
            case 'post':
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
                break;
            case 'get':
                curl_setopt($ch, CURLOPT_HTTPGET, 1);
                break;
            case 'delete':
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
                break;
            case 'put':
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
            default:
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
                break;
        }
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $output = curl_exec($ch);
        if (curl_errno($ch)) {
            echo 'Errno'.curl_error($ch);
        }
        curl_close($ch);
        return $output;
    }
}
